﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DevOnServer
{
    public class CPlayerObject : CCreature
    {
        public CPlayerObject(CGamePlayer player, int id, CWorld world)
            : base(id, world, null)
        {
            Inventory = new CInventory(this);
            Player = player;

            CCharacter character = player.Character;

            JobProp = world.Server.DataManager.JobProperties[character.Job];
            Position = character.Position;
            Rotation = character.Rotation;
            HP = character.HP;
            MP = character.MP;
            FP = character.FP;
        }

        public override ObjType Type
        {
            get
            {
                return ObjType.Player;
            }
        }

        public CGamePlayer Player { get; private set; }

        public CInventory Inventory { get; private set; }

        public CJobProp JobProp { get; private set; }

        public int FOR;

        public int END;

        public int DEX;

        public int INT;

        public int HPMax;

        public int FPMax;

        public int MPMax;

        public int FP;

        public int MP;

        public int CriticalChance;

        public int HPRecovery;

        public int FPRecovery;

        public int MPRecovery;

        public void addMobExp(long exp)
        {
            CLevelExp levelExp = World.Server.DataManager.ExpTable[Player.Character.Level];

            if (exp > levelExp.MaxExp)
                exp = levelExp.MaxExp;

            changeExp(Player.Character.Exp + exp); // à faire : prendre en compte un coeff. global d'exp
        }

        public void changeExp(long exp)
        {
            CCharacter character = Player.Character;

            while (exp < 0)
            {
                if (character.Level <= 1)
                {
                    exp = 0;
                    break;
                }

                character.Level--;
                exp += World.Server.DataManager.ExpTable[Player.Character.Level].LevelUp;
            }

            Player.Character.Exp = exp;

            int oldLvl = character.Level;

            while (character.Exp >= World.Server.DataManager.ExpTable[Player.Character.Level + 1].LevelUp)
            {
                character.Level++;
                character.Exp -= World.Server.DataManager.ExpTable[Player.Character.Level].LevelUp;
                character.StatPoints += 2;
                character.SkillPoints += 2;
            }

            if (oldLvl != character.Level)
            {
                calculateStats();

                HP = HPMax;
                FP = FPMax;
                MP = MPMax;
            }

            World.sendToLocalArea(this, (CPacketCreator.levelInfos(this)));
        }

        public void calculateStats()
        {
            CCharacter character = Player.Character;

            FOR = 0;
            END = 0;
            DEX = 0;
            INT = 0;

            FOR += character.FOR;
            END += character.END;
            DEX += character.DEX;
            INT += character.INT;

            CriticalChance = (int)(JobProp.Critical * (float)(DEX / 10.0f));

            HPMax = (int)((END * 0.02f + 1)
                * (character.Level * (JobProp.FactorMaxHP * 0.5f) * ((character.Level + 1) * 0.25f))
                + END * 10 + 80);

            FPMax = (int)((2 * character.Level + END * 6) *
                JobProp.FactorMaxFP + END *
                JobProp.FactorMaxFP);

            MPMax = (int)((2 * character.Level + INT * 8) *
                JobProp.FactorMaxMP + 22 + INT *
                JobProp.FactorMaxMP);
        }

        public override void damage(CAttackResult result, CCreature attacker)
        {
            World.sendToLocalArea(this, CPacketCreator.damage(attacker, this, result.Damage, result.Flags));

            HP -= result.Damage;

            if (HP <= 0)
            {
                HP = 0;
                result.Kill = true;
                kill(DeathType.Mob, attacker);
            }
        }

        public override void kill(DeathType death, CCreature killer)
        {
            World.sendToLocalArea(this, CPacketCreator.moverDeath(this));
        }

        public override void update()
        {
            _updatePosition();
        }

        public void teleport(CVec3Df pos, CWorld world)
        {
            Position = pos;

            if (World == world)
            {
                world.sendToLocalArea(this, CPacketCreator.positionUpdate(this));
                onChangePosition();
            }
            else
            {
                world.transfertObject(this, world);
            }

            m_nextPosUpdate = 0;
        }

        public override CAttackResult attack(CCreature target, int attackMotion = 30)
        {
            m_attackResult.Damage = 0;
            m_attackResult.Flags = 0;

            if (!target.IsAlive)
                return m_attackResult;

            m_attackResult.Damage = CRandom.random(50, 60);
            m_attackResult.Flags |= (CRandom.random(0, 5) == 0 ? (int)AttackFlags.Critical : 0);

            World.sendToLocalArea(this, CPacketCreator.attack(this, target, attackMotion));

            target.damage(m_attackResult, this);

            return m_attackResult;
        }

        public void updateCharacter()
        {
            CCharacter character = Player.Character;

            character.Position = Position;
            character.Rotation = Rotation;
            character.HP = HP;
            character.FP = FP;
            character.MP = MP;

            if (World != null)
                character.WorldID = World.ID;
        }
    }
}
